/* ---------------------report the temperature------------------------
 *1.判断是否存在数据库db文件和表，不存在就创建，存在就不创建
 *2.支持命令行传ip地址，端口号，域名，产品序列号,间隔时间,等参数
 *3.客户端网络断开时自动保存断开时数据
 *4.连接服务器时判断是否有断电时保留的数据
 *5.有保留的数据就将数据发送给服务器
 *6.在服务器网络恢复时自动重连服务器
 *7.保证在发送数据库数据时能够精确采样数据
 *------------------------------------------------------------------*/

#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <netdb.h>
#include "gettemp.h"
#include <syslog.h>
#include <libgen.h>
#include <signal.h>
#include <time.h>
#include <sqlite3.h>
#include "logger.h"
#include "sqlaction.h"
#include "socketinit.h"

/*------------------------------全局变量-------------------------*/
int 			p_stop = 0;//程序运行标志

/*-----------------------------函数声明--------------------------*/
void sign_handle(int signum)
{
	p_stop = 1;
	log_info("The program exit now!\n");
}

void useage(char *progname)
{
	printf("%s useage:\n",progname);
	printf("-i(--ipaddr):specify server IP address\n");
	printf("-p(--port):specify server  port\n");
	printf("-h(--help):print this help information\n");
	printf("-d(--daemon):Let the Program run in the background\n");
	printf("-s(--sn):product ID\n");
	printf("-t(--time):Sampling interval time\n");
	printf("for example:proname -i 127.0.0.0 -p 1111 (-s [int i]) (-d) (-t [int i]) ");
	return;
}
int compose_information(char *buffer,info_temp_t *temp_information,struct sn_time_interval *sti);
int daemon_switch(int daemon_ctl);
void signal_init();

/*-------------------------------主函数----------------------------*/
int main(int argc, char **argv)
{
	int							sockfd = -1;
	int							rv = 1;
	int							i=0;
	struct sockaddr_in			servaddr;
	char						*servip=NULL;
	int							port=0;
	char						buf[128];
	char						*idbuf;
	struct hostent				*getname=NULL;
	int							opt;
	int							idx;
	int							daemon_ctl=0;
	char						*proname=NULL;
	info_temp_t					temp_infor;//采集信息结构体
	struct sn_time_interval		sn_tm_intv={0,0,30};
	float						temp;
	int							log_flag=1;//打印日志标志
	int							max_row=1;//数据主键最大id
	int							sample=0;//采样标志
	char						*mark="/";//分隔符
	struct option				opts[] = {
		{"ipaddr",required_argument,NULL,'i'},
		{"port",required_argument,NULL,'p'},
		{"help",no_argument,NULL,'h'},
		{"daemon",no_argument,NULL,'d'},
		{"sn",required_argument,NULL,'s'},
		{"time",required_argument,NULL,'t'},
		{NULL,0,NULL,0}
	};


	//获取此程序名字
	proname=basename(argv[0]);
	//命令行解析
	while((opt = getopt_long(argc,argv,"i:p:hds:t:",opts,&idx)) != -1)
	{
		switch(opt)
		{
			case 'i':
				 servip = optarg;
				 break;
			case 'p':
				 port = atoi(optarg);
				 break;
			case 'h':
				 useage(argv[0]);
				 return 0;
			case 'd':
				 daemon_ctl=1;
				 break;
			case 's':
				 sn_tm_intv.sn = atoi(optarg);
				 break;
			case 't':
				 sn_tm_intv.interval=atoi(optarg);
				 break;
		}
	}
	if(!(servip&&port))
	{
		useage(argv[0]);
		return 0;
	}

	//是否进入守护进程，后台运行
	rv=daemon_switch(daemon_ctl);
	if(rv<0)
		log_error("daemon_switch failure!\n");

	//初始化信号,并安装信号
	signal_init();

	//设置日志文件信息，初始化
    if( logger_init("stdout", LOG_LEVEL_INFO) < 0)
    {
        fprintf(stderr, "initial logger system failure\n");
        return -1;
    }


	//create a database flie and a table
	sql_create_db_tb("temp.db");

	//获取一个最初时间以便实现开机就采样
	sn_tm_intv.last_time=0;

	while(!p_stop)
	{	
		
		/********************************
		 *检查是否连接，检查连接是否断开
		 *断开重连，断开且sockfd大于0重置sockfd
		 ********************************/
		if(sockfd<0)
		{
			sockfd = socket_connect_server(servaddr,port,servip);
		}
		else if(socket_check_connect(sockfd)<0)
		{
			socket_term(&sockfd);
		}

   		/********************************
		 *到达采样时间
		 *将数据放入数据库，连接成功是发送数据库
		 ********************************/
		if(sampling_timer(&sn_tm_intv))
		{
			//组合温度数据
			rv = compose_information(buf,&temp_infor,&sn_tm_intv);
			if(rv<0)
				break;
			if(sockfd<0)
			{
				log_error("The socket connect failure\n");
				rv=sql_insert_one_data(&temp_infor);
				if(rv<0)
				{
					log_error("Insert data failure");
					continue;
				}
			}
			else
			{	
				log_info("Connect server[%s:%d] successfully!\n",servip,port);
				rv=socket_write(&sockfd,buf,strlen(buf));
				if(rv<0)
					continue;
				max_row=sql_number_of_row();
				//遍历数据库数据并发送
				for(i=0;i<max_row;i++)
				{
					rv=sql_select_one_data(&temp_infor);
					if(rv>0)//读取数据，存在temp_infor中成功返回0
					{
						memset(buf,0,sizeof(buf));
						snprintf(buf,sizeof(buf),"%s/%s/%s",temp_infor.prod_id,temp_infor.ttime,temp_infor.temp);

						//发送
						rv=socket_write(&sockfd,buf,strlen(buf));
						if(rv<0)
						{
							rv=socket_check_connect(sockfd);
							if(rv<0)
								break;
						}
						sql_delete_one_data();
					}
					else
						continue;
					//发送数据时同时也监控采样定时器是否采样数据到来
					rv = sampling_timer(&sn_tm_intv);
					if(rv)
					{
						compose_information(buf,&temp_infor,&sn_tm_intv);
						rv=socket_write(&sockfd,buf,strlen(buf));
						if(rv<0)
						{
							rv=socket_check_connect(sockfd);
							if(rv<0)
								break;
						}

					}
				}
				//遍历发送完之后删除表中所有数据
				//sql_delete_all_data();

				log_info("All data in the database has been sent!\n");
			}
		}

	}
	sql_term();
	socket_term(&sockfd);
	logger_term();
}

int compose_information(char *buffer,info_temp_t *temp_information,struct sn_time_interval *sti)
{
	float				temp;
	int					rv = -1;
	char				buf[128];
	struct tm 			*str_last_time;
	
	if(NULL==buffer||NULL==temp_information||NULL==sti)
	{
		log_error("The parameter is NULL!");
		return -1;
	}
	rv = get_temperature(&temp);//获取温度
	if(rv<0)
	{
		log_error("get temperature failure!");
		return -1;
	}

	str_last_time=localtime(&(sti->last_time));
	snprintf(temp_information->prod_id,8,"dra%04d",sti->sn);
	snprintf(temp_information->ttime,21,"%04d-%02d-%02d %02d:%02d:%02d",
			str_last_time->tm_year + 1900,str_last_time->tm_mon+1,str_last_time->tm_mday,
			str_last_time->tm_hour,str_last_time->tm_min,str_last_time->tm_sec);
	snprintf(temp_information->temp,6,"%3.1fC",temp);

	//重组buf
	memset(buffer,0,sizeof(buffer));
	memset(buf,0,sizeof(buf));

	snprintf(buf,sizeof(buf),"%s/%s/%s",temp_information->prod_id,
			temp_information->ttime,temp_information->temp);
	strcpy(buffer,buf);
	return 1;

}
int daemon_switch(int daemon_ctl)
{
	if(daemon_ctl)
	{
		if(daemon(1,1)<0)
		{
			log_error("Program daemon() failure: %s\n", strerror(errno));
			return -1;
		}
		else
		{
			log_info("program daemon\n");
		}	
	}
	return 0;
}
void signal_init()
{
	struct sigaction	sigact,sigign;

	sigact.sa_handler = sign_handle;
	sigemptyset(&sigact.sa_mask);
	sigact.sa_flags = 0;

	sigign.sa_handler = SIG_IGN;
	sigemptyset(&sigign.sa_mask);
	sigign.sa_flags = 0;

	//插入kill,CTRL+C,SIGPIPE处理信号
	sigaction(SIGTERM,&sigact,0);
	sigaction(SIGINT,&sigact,0);
	sigaction(SIGPIPE,&sigign,0);

}

